在 Next.js 中使用 Sanity Webhook 很簡單,官方也有準備好各種的套件給使用者使用,如果是有跟著本系列開啟 Next.js 專案的話,可以使用 next-sanity 底下的 webhook。
// ./app/api/revalidate/route.ts
import { revalidateTag } from "next/cache";
import { type NextRequest, NextResponse } from "next/server";
import { parseBody } from "next-sanity/webhook";
export async function POST(req: NextRequest) {
const { body, isValidSignature } = await parseBody<{
_type: string;
slug?: string | undefined;
}>(req, process.env.NEXT_PUBLIC_SANITY_HOOK_SECRET);
if (!isValidSignature) {
return new Response("Invalid Signature", { status: 401 });
}
if (!body?._type) {
return new Response("Bad Request", { status: 400 });
}
revalidateTag(body?._type);
return NextResponse.json({
status: 200,
revalidated: true,
now: Date.now(),
body,
});
}
先找官方的範例,主要是使用 next-sanity/webhook
中的 parseBody()
方法來對 Sanity 傳過來的請求進行驗證,並且過濾出傳送過來的 body 內容。
可以看到 parseBody()
回傳了 { body, isValidSignature }
。
顧名思義 isValidSignature 就是是否通過驗證的標籤,如果是 false
就是沒有驗證通過。
而 body 則是被更動的內容資料物件,以我隨便更動一篇文章為例:
{
_rev: 'Tpe1Rj6o9fDmGqbWvmFLMY',
slug: { current: 'tomcat-下載、簡介' },
_createdAt: '2024-09-30T03:04:01Z',
tags: [ 'Tomcat', 'Java' ],
title: 'Tomcat 下載、簡介',
_updatedAt: '2024-10-10T10:42:18Z',
_id: 'zyNWCmL2nqND6MCG2waPb',
_type: 'blogPost',
subtitle: 'Tomcat 下載、簡介',
content: '講 Tomcat 之前要先稍微講一下什麼是 __容器 ( Container )__,\n' +
'其實容器也就是一個 Java 寫的程式,運行於我們的 JVM 上面,不同的容器負責不同的工作。\n' +
'__Web 容器 (Web Container)__\n' +
// ...
'ok! 這樣我們的 Tomcat 開發環境就算是裝好了~',
publishedAt: '2020-05-04',
heroImage: { _type: 'image', asset: [Object] }
}
可以看到 body 是全部的內容,並不是只有被更動到的欄位內容。
若是想要有些更複雜的回傳可以針對建立的 Projection 進行編輯:
這邊舉幾個例子,如果我設定成這樣:
{ _type, title }
回傳就是這樣:
{
_type: 'blogPost',
title: 'Tomcat 下載、簡介'
}
基本上回傳就是自己指定的內容。
再來還有一些特別的 function,Sanity 將其歸類在 Delta functions,包含了 before()
, after()
等等的函式,在這邊直接展示幾項吧!
回傳更新前、更新後的值
假設這樣設定:
{ _type, title, "oldTag": before().tags, "newTag": after().tags }
然後我對 tags
這個欄位進行更新,就會回傳這樣的:
{
_type: 'blogPost',
title: 'Tomcat 下載、簡介',
oldTag: [ 'Tomcat' ],
newTag: [ 'Tomcat', 'Java' ]
}
監聽指定欄位是否有更定,回傳值是 boolean
{ _type, title, "hasTagsChanged": delta::changedAny(tags) }
這樣就是指定了監聽 tags
欄位是否有更動,如果我有更動到 tags
欄位就會回傳 true
,沒有的話就是 false
。
{ _type: 'blogPost', title: 'Tomcat 下載、簡介', hasTagsChanged: true } // <- 有更動
{ _type: 'blogPost', title: 'Tomcat 下載、簡介', hasTagsChanged: false } // <- 沒更動
同時還可以一次指定多格欄位,格式是這樣的:
( 注意還有一層小括號括起來哦! )
delta::changedAny((publishedAt, tags))